from datetime import datetime, timedelta

from flask import current_app
import jwt  # pyjwt库中可以使用hash SHA 和MD5算法,其中，SHA和MD5这两种算法是不能逆向获取值的。无法逆向破解，安全性跟高。
from jwt import PyJWTError

from comment.models.user import User
from comment.utils.const import SECRET_KEY, JWT_EXPIRY_SECOND


def generate_token(uid):
    '''
    根据已经登陆之后的用户ID生成token
    :param uid: 用户ID
    :return:
    '''
    # 要传三个参数，参数一：payload，是一个字典，里面包括要加密的用户ID和token有效时间
    # 参数二：秘钥。
    # 参数三：指定算法。
    payload = {
        'id': uid,
        # exp代表token有效时间，而且必须是标准时间。exp这个字段是定死的，不可以用别的名字。
        'exp': datetime.utcnow() + timedelta(seconds=JWT_EXPIRY_SECOND)  # 这句代码决定了生成的token的有效时间是从生成的那一刻开始计算的。
    }
    s = jwt.encode(payload=payload, key=SECRET_KEY, algorithm='HS256')  # 这句代码直接生成token了
    return s


def verify_tokens(token_str):
    '''
    验证token,并且验证之后返回用户ID
    :param token_str:
    :return:
    '''
    try:
        # 本质上就是一个解密的过程
        data = jwt.decode(token_str, key=SECRET_KEY, algorithms='HS256')  # 一定要记住，这里这个algorithms比上面的多了一个s
        current_app.logger.info(data)
    except PyJWTError as e:
        current_app.logger.info(e)
        return {'message': 'token验证失败'}
    # 如果token验证成功，还需要看看用户状态是否正常
    user = User.query.filter(User.id == data['id']).first()
    if user and user.status != 0:  # 如果这个用户存在并且状态不等于0
        return {'message': '数据库中的用户状态过期'}
    return {'id': user.id}
